/**
 * dbms-sjtu
 * Page.java created at Jul 19, 2011
 */
package dbms.disk;

import java.nio.ByteBuffer;

import dbms.Constants;
import dbms.server.DbmsServer;

/**
 * all operation of a page
 * @author weapon
 */
public class Page {
	public DiskManager dbFile;
	
	/**
	 * the buffer of this page, default value is 1024
	 */
	public ByteBuffer contents;
	
	/**
	 * init the field contents, with ByteBuffer.allocateDirct(int capacity)
	 */
	public Page(){
		dbFile = DbmsServer.dataBaseFile;
		contents = ByteBuffer.allocateDirect(Constants.BLOCKSIZE);
	}
	
	/*public static final int STR_SIZE(int n) {
	    float bytesPerChar = Charset.defaultCharset().newEncoder().maxBytesPerChar();
	    return Constants.INT_SIZE + (n * (int)bytesPerChar);
	}*/
	
	/**
	 * read the page's content to buffer
	 * @param pageNum : the block num of the db file
	 */
	public synchronized void read(int pageNum){
		dbFile.readPage(pageNum, contents);
	}
	
	/**
	 * write the content of the buffer to specific block of db file
	 * @param pageNum : the block num of the db file
	 */
	public synchronized void write(int pageNum){
		dbFile.writePage(pageNum, contents);
	}
	
	/**
	 * append a new block, if the db file has no available space
	 */
	public synchronized int append(){
		return dbFile.append(contents);
	}
	
	/**
	 * get the int value at specific position of the buffer
	 * @param offset : the specific position of the int value
	 * @return the int value
	 */
	public int getInt(int offset){
		contents.position(offset);
		return contents.getInt();
	}
	
	/**
	 * write the int value to the specific position of the buffer
	 * @param offset : the specific position of the int value 
	 * @param value : the int value 
	 */
	public void setInt(int offset, int value){
		contents.position(offset);
		contents.putInt(value);
	}
	
	
	/**
	 * get the float value at specific position of the buffer
	 * @param offset : the specific position of the float value
	 * @return the float value
	 */
	public float getFloat(int offset){
		contents.position(offset);
		return contents.getFloat();
	}
	
	/**
	 * write the float value to the specific position of the buffer
	 * @param offset : the specific position of the float value 
	 * @param value : the float value 
	 */
	public void setFloat(int offset, float value){
		contents.position(offset);
		contents.putFloat(value);
	}
	
	/**
	 * get a String value from specific position
	 * First, get the String value's length;
	 * Then, get the String value.
	 * So all cost bytes is 4 + n; 
	 * @param offset : the specific position of this ByteBuffer
	 * @return : the String value
	 */
	public String getString(int offset, int length){
		contents.position(offset);
		byte[] byteval = new byte[length];
		contents.get(byteval);
		return new String(byteval);
	}
	
	/**
	 * write a String value from specific position
	 * First, write the String value's length;
	 * Then, write the String value.
	 * So all cost bytes is 4 + n; 
	 * @param offset : the specific position of this ByteBuffer
	 * @param val : the String value which will write
	 */
	public void setString(int offset, String val){
		contents.position(offset);
		byte[] byteval = val.getBytes();
		if(byteval.length > contents.remaining()){
			throw new RuntimeException("Can not write String to " +
					"this page " + this.toString());
		} else {
			//contents.putInt(byteval.length);
			contents.put(byteval);
		}
	}
}
